<?php
declare(strict_types=1);
/**
 * Guzzle HTTP 客户端
 */
namespace Service\HttpServer;

use Service\BaseService;
use Service\Code\Normal;

class HttpCurl extends BaseService
{
    public $postFields = null;
    public $header = [];
    public $timeOut = 30;
    
    /**
     * 发起http请求
     * @param string $url
     * @param array $data
     * @param string $method
     * @param string $format
     */
    public function apiRequest( $url = null, $data = [] ,$method = 'POST',$format = 'form-data',$hedaer = [])
    {
        //设置头部
        self::setHeader($format,$hedaer);
        
        //设置字段
        self::setPostFields($format,$data);
        
        //初始化curl句柄
        $ch = curl_init();
        
        //设置请求方式
        self::setDataOpt($method,$ch);
        
        //设置请求协议
        if (self::is_https($url)) {
            self::https_setopt($ch);
        }
        
        //请求超时时间
        $timeOut = $this->timeOut;
        
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
        curl_setopt($ch,CURLOPT_TIMEOUT_MS, $timeOut * 1000);
        curl_setopt($ch,CURLOPT_CONNECTTIMEOUT_MS, $timeOut * 1000);
        curl_setopt($ch,CURLOPT_HTTPHEADER,$this->header);
        curl_setopt($ch,CURLOPT_FORBID_REUSE,1);
        curl_setopt($ch,CURLOPT_FRESH_CONNECT,1);
        curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_1);
        
        //获取curl结果信息
        $result     = curl_exec($ch);
        $code       = curl_getinfo($ch,CURLINFO_HTTP_CODE);
        $error      = curl_error($ch);
        $errorCode  = curl_errno($ch);
        curl_close($ch);
        return [
            'result'    => $result,
            'httpCode'  => $code,
            'error'     => $error,
            'errorCode' => $errorCode
        ];
    }
    
    /**
     * 判断是否https请求
     * @param $url
     * @return bool
     */
    private function is_https($url)
    {
        $httpProtocol = parse_url($url, PHP_URL_SCHEME);
        if ($httpProtocol == 'https') {
            return true;
        }
        return false;
    }
    
    /**
     * 设置https请求选项
     * @param $ch   curl句柄
     * @return bool
     */
    private function https_setopt($ch)
    {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);    // 不验证https证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        return true;
    }
    
    /**
     * 设置数据选项
     * @param $ch
     * @param string $data
     * @return bool
     */
    private function setDataOpt($method, $ch)
    {
        $data = $this->postFields;
        $method = strtolower($method);
        if($method == 'post'){
            //post 表单方式
            curl_setopt($ch,CURLOPT_POST,true);
            curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
        } elseif ($method == 'put') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        } elseif ($method == 'delete') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
        } elseif ($method == 'head') {
            curl_setopt($ch, CURLOPT_NOBODY, true);
            curl_setopt($ch, CURLOPT_HEADER, true);
        }
        return true;
    }
    
    private function setHeader( $format ,$hedaer )
    {
        if( $format == 'json' ) {
            $current_header = [
                'Content-Type: application/json'
            ];
        } else if( $format == 'x-www-form-urlencoded'){
            $current_header = [
                'Content-Type: application/x-www-form-urlencoded'
            ];
        } else {
            $current_header = $hedaer;
        }
        
        $this->header = $hedaer ? $hedaer : $current_header ;
    }
    
    private function setPostFields($format,$data)
    {
        if( $format == 'json' ) {
            $data = json_encode($data);
        } else {
            is_array($data) && $data = http_build_query($data);
        }
        $this->postFields = $data;
    }
    
    /**
     * 装数据
     * @param array $data
     */
    public function getContents( $data = [] )
    {
        $pieces = [];
        foreach ($data as $key => $val ) {
            $pieces[] = "{$key}={$val}";
        }
        return implode("&", $pieces);
    }
    
    /**
     * 获取微服务接口返回码
     * @param array $response
     */
    public function getMicorServiceResponseInfo( $response = [] )
    {
        $result = @json_decode($response['result'],true);
        $result = empty($result) ? $response['result'] : $result;
        $httpCode = $response['httpCode'];
        $message = $httpCode == Normal::SUC ? "请求成功" : ($result['message'] ?? "服务接口请求失败，请稍后再试【{$response['result']}】");
        return Normal::returnCode($httpCode,$message,$result);
    }
}